#include "serveurtcp.h"

ServeurTcp :: ServeurTcp (QObject *parent)
{
    //listen(QHostAddress::Any,4000);
    m_socket = NULL;
    QObject:: connect(this, SIGNAL(newConnection()), this, SLOT(connetionRequest()));
    m_block_size = 0;
}

void ServeurTcp::lunch(const QString& port)
{
    m_port = port;
    listen(QHostAddress::Any,m_port.toInt());
    m_socket = NULL;
    m_block_size = 0;
}


void ServeurTcp::connetionRequest()
{
    if (m_socket == NULL)
    {
        m_socket = nextPendingConnection();
        QObject::connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()) );
        QObject:: connect(m_socket, SIGNAL(disconnected ()), this, SLOT(reset_socket()));
        sendAiModel();
        sendIts();
        emit socket_connected();
    }
}

IAlib::AiCommand * ServeurTcp::AiCommandFromByteArray(QDataStream &data)
{
    IAlib::AiCommand::CommandType cmd_type;
    int i_temp;
    data>>i_temp;
    cmd_type = (IAlib::AiCommand::CommandType) i_temp;
    switch (cmd_type)
    {
        case IAlib::AiCommand::COMMAND_CALL:
        {
            IAlib::AiCommandCall * cmd = new IAlib::AiCommandCall();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_CALL_CLOSE:
        {
            IAlib::AiCommandCallClose * cmd = new IAlib::AiCommandCallClose();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_CALL_RESPONSE:
        {
            IAlib::AiCommandCallReponse * cmd = new IAlib::AiCommandCallReponse();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_SEND_FAX:
        {
            IAlib::AiCommandSendFax * cmd = new IAlib::AiCommandSendFax();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_MOVE_TO_ACTOR:
        {
            IAlib::AiCommandMoveToActor * cmd = new IAlib::AiCommandMoveToActor();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_MOVE_TO_AI:
        {
            IAlib::AiCommandMoveToIA * cmd = new IAlib::AiCommandMoveToIA();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_MOVE_TO_ADRESSE:
        {
            IAlib::AiCommandMoveToAdresse * cmd = new IAlib::AiCommandMoveToAdresse();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_MOVE_TO_POSITION:
        {
            IAlib::AiCommandMoveToAdresse * cmd = new IAlib::AiCommandMoveToAdresse();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_END_TRIP:
        {
            IAlib::AiCommandEndTrip * cmd = new IAlib::AiCommandEndTrip();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_INFORME:
        {
            IAlib::AiCommandInform * cmd = new IAlib::AiCommandInform();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_ERROR:
        {
            IAlib::AiCommandError * cmd = new IAlib::AiCommandError();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_PROXIMITY_DIALOG:
        {
            IAlib::AiCommandDialogProximity * cmd = new IAlib::AiCommandDialogProximity();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_PROXIMITY_DIALOG_REPONSE:
        {
            IAlib::AiCommandProximityDialogReponse * cmd = new IAlib::AiCommandProximityDialogReponse();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_DIALOG_CLOSE:
        {
            IAlib::AiCommandDialogClose * cmd = new IAlib::AiCommandDialogClose();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_UNDEF:
        {
            IAlib::AiCommandError * cmd = new IAlib::AiCommandError();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_AI_ACTION:
        {
            IAlib::AiCommandAction * cmd = new IAlib::AiCommandAction();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        case IAlib::AiCommand::COMMAND_DIALOG_PHRASE:
        {
            IAlib::AiCommandPhrase * cmd = new IAlib::AiCommandPhrase();
            QByteArray byte_array;
            data>>byte_array;
            cmd->fromByteArray(byte_array);
            return cmd;
            break;
        }
        default:
        {
            return NULL;
            break;
        }
    }
}

void ServeurTcp::readSocket()
{
    QDataStream in(m_socket);
    if ( m_block_size == 0 )
    {
       if (m_socket->bytesAvailable() < (int)sizeof(quint16)) return;
       in >> m_block_size;
    }
    if ( m_socket->bytesAvailable() < m_block_size )
    {
        return;
    }
    IAlib::AiCommand *cmd;
    quint8 msg_type;
    in >> msg_type;
    switch (msg_type)
    {
    case IAlib::Model::NW_TYPE_COMMAND :
        {
            cmd = AiCommandFromByteArray(in);
            m_cmd_in.append(cmd);
            emit cmdIn("client",  cmd);
            break;
        }
    case IAlib::Model::NW_TYPE_ITS_ACTION :
        {
            QByteArray byte_array;
            in >> byte_array;
            IAlib::ItsAction action;
            action.fromByteArray(byte_array);
            emit itsActionReceived(action);
            break;
        }
    case IAlib::Model::NW_TYPE_CONFIG:
    {
        QString path;
        in>>path;
        m_model->setDialogPath(path);
    }
    }
    m_block_size = 0;
}

//-----------------------------------------------------------------------

void ServeurTcp::sendAiModel()
{
    if (m_socket != NULL)
    {
        QDataStream data(m_socket);
        QByteArray byte_array = m_model->toByteArray();
        quint16 size = byte_array.size()+ sizeof(quint8);
        data<<size;
        quint8 msg_type = 1;
        data<<msg_type;
        data<<byte_array;
    }
}

void ServeurTcp::sendIts()
{
    if (m_socket != NULL)
    {
        QDataStream data(m_socket);
        QByteArray byte_array = m_model->getIts()->toByteArray();
        quint16 size = byte_array.size()+ sizeof(quint8);
        data<<size;
        quint8 msg_type = 5;
        data<<msg_type;
        data<<byte_array;
    }
}

//----------------------------------------------------------------------

void ServeurTcp::readData()
{
    if (m_socket != NULL)
    {
        readSocket();
    }
}

void ServeurTcp::clearCmdIn()
{
    for (int i = 0; i < m_cmd_in.size(); i++)
    {
        delete(m_cmd_in[i]);
    }
    m_cmd_in.clear();
}

void ServeurTcp::sendCmd(QTcpSocket * socket, QList<IAlib::AiCommand*> list_cmd)
{
    for (int i = 0; i < list_cmd.size(); i++ )
    {
        QDataStream data(socket);
        quint16 msg_size = list_cmd[i]->toByteArray().size() + sizeof(quint8) + sizeof(int);
        quint8 msg_type = 0;  // msg type AiCommand (temporary)
        data << msg_size;
        data << msg_type;
        data << list_cmd[i]->getType();
        data << list_cmd[i]->toByteArray();
    }
}

void ServeurTcp::sendMonitoringEvent(const QString& time, const QString& id_agent, IAlib::Model::MonitoringEventType type, const QString& param)
{
	QByteArray byte_array;
	QDataStream temp(&byte_array, QIODevice::WriteOnly);
	temp<<time;
	temp<<id_agent;
	temp<<type;
	temp<<param;
    if (m_socket != NULL)
	{
        QDataStream data(m_socket);
		quint16 msg_size = byte_array.size() + sizeof(quint8);
		quint8 msg_type = 3;
		data<<msg_size;
		data<<msg_type;
		data<<time;
		data<<id_agent;
		data<<type;
		data<<param;
	}
}

//-------------------------------------------------------------------------

void ServeurTcp::sendItsAction(const IAlib::ItsAction &action)
{
    QByteArray byte_array = action.toByteArray();
    if (m_socket != NULL)
    {
        QDataStream data(m_socket);
        quint16 size = byte_array.size() + sizeof(quint8);
        data<<size;
        quint8 msg_type = 4;
        data<<msg_type;
        data<<byte_array;
    }
}

void ServeurTcp::addCmd(IAlib::AiCommand * cmd)
{
    m_cmd_in.append(cmd);
}

void ServeurTcp::setCmdOut(const QList<IAlib::AiCommand*> &list_cmd)
{
    m_cmd_out = list_cmd;
    if (m_socket != NULL)
    {
        sendCmd(m_socket, m_cmd_out);
    }
}

void ServeurTcp::reset_socket()
{
    m_socket = NULL;
    emit socket_disconnected();
}

quint16 ServeurTcp::sendUpdate(IAlib::Model * model)
{
	QByteArray byte_array = model->refreshInfoToByteArray();
    if (m_socket != NULL)
    {
        QDataStream data(m_socket);
        quint16 size = byte_array.size() + sizeof(quint8);
        data<<size;
        quint8 msg_type = 2;
        data<<msg_type;
        data<<byte_array;
    }
	return byte_array.size();
}
